/// <reference path="../devextreme/ts/jquery.d.ts" />
/// <reference path="../devextreme/ts/dx.all.d.ts" />

($ => {
    class TemplatePreview {
        constructor(options) {
            this.options = options || {};
            this.init();
        }

        init() {
            if (this.options.container) {
                this.$toolbar = this.createToolbar();
                $(this.options.container).append(this.$toolbar).append(this.createPreviewPanel());
            }
        }

        setReadOnly(readOnly) {
            this.readOnly = readOnly;
            this.$toolbar.dxToolbar('instance').repaint();
        }

        createToolbar() {
            return $('<div class="preview-toolbar" />').dxToolbar({
                items: [
                    {
                        location: 'before',
                        widget: 'dxButton',
                        visible: !this.readOnly,
                        options: {
                            text: '替换',
                            icon: 'chevronleft',
                            onClick: () => {
                                if (this.options.onReplaceTemplate && !this.template.isDirectory) {
                                    this.options.onReplaceTemplate(this.template);
                                }
                            },
                        },
                    },
                    {
                        location: 'before',
                        widget: 'dxButton',
                        visible: !this.readOnly,
                        options: {
                            text: '追加',
                            icon: 'chevrondoubleleft',
                            onClick: () => {
                                if (this.options.onAppendTemplate && !this.template.isDirectory) {
                                    this.options.onAppendTemplate(this.template);
                                }
                            },
                        },
                    },
                    {
                        location: 'before',
                        widget: 'dxButton',
                        visible: this.options.allowEdit ?? false,
                        options: {
                            text: '保存',
                            icon: 'save',
                            onClick: () => {
                                if (this.options.onSaveTemplate) {
                                    this.options.onSaveTemplate().then(template => {
                                        this.previewTemplate(template);
                                    });
                                }
                            },
                        },
                    },
                ],
            });
        }

        createPreviewPanel() {
            this.$imageSeeing = $('<div class="image-seeing-content content">无</div>');
            this.$imageDiagnosis = $('<div class="image-diagnosis-content content">无</div>');
            this.$imageOpinion = $('<div class="image-opinion-content content">无</div>');
            return $('<div class="preview-panel" />')
                .append($('<div class="image-seeing-title title">影像所见</div>'))
                .append(this.$imageSeeing)
                .append($('<div class="image-diagnosis-title title">影像诊断</div>'))
                .append(this.$imageDiagnosis)
                .append($('<div class="image-opinion-title title">影像建议</div>'))
                .append(this.$imageOpinion)
                .dxScrollView({
                    showScrollbar: 'onHover',
                });
        }

        previewTemplate(template) {
            template ??= {};
            this.template = template;
            this.$imageSeeing.html(template.imageSeeing ?? '无');
            this.$imageDiagnosis.html(template.imageDiagnosis ?? '无');
            this.$imageOpinion.html(template.imageOpinion ?? '无');
        }
    }

    class TemplateTree {
        constructor(options) {
            this.options = options || {};
            this.init();
        }

        init() {
            if (this.options.container) {
                this.$toolbar = this.createToolbar();
                $(this.options.container).append(this.$toolbar).append(this.createTemplateTree());
            }
        }

        selectTemplateDirectory(directories) {
            return new Promise(resolve => {
                directories = [
                    ...directories,
                    {
                        id: 'root',
                        name: '模板',
                    },
                ];
                const $treeView = $('<div class="clone-template-treeview" />').dxTreeView({
                    dataSource: directories.map(item => {
                        item.icon = 'folder';
                        item.expanded = true;
                        if (item.id !== 'root') {
                            item.parentId = item.parentId || 'root';
                        }
                        return item;
                    }),
                    keyExpr: 'id',
                    displayExpr: 'name',
                    parentIdExpr: 'parentId',
                    dataStructure: 'plain',
                    selectionMode: 'single',
                    onItemClick: e => {
                        if (e.node.expanded) {
                            e.component.collapseItem(e.itemData);
                        } else {
                            e.component.expandItem(e.itemData);
                        }
                        $treeView.dxTreeView('instance').selectItem(e.itemData);
                    },
                });
                const $popup = $('<div class="clone-template-popup" />');
                $(document.body).append($popup);
                $popup.dxPopup({
                    title: '克隆到',
                    showTitle: true,
                    visible: true,
                    maxWidth: 500,
                    maxHeight: '80vh',
                    toolbarItems: [
                        {
                            toolbar: 'bottom',
                            location: 'after',
                            widget: 'dxButton',
                            options: {
                                text: '确定',
                                onClick: () => {
                                    const treeViewInstance = $treeView.dxTreeView('instance');
                                    const selectedNodeKeys = treeViewInstance.getSelectedNodeKeys();
                                    if (selectedNodeKeys.length > 0) {
                                        $popup.dxPopup('instance').hide();
                                        resolve(selectedNodeKeys[0] === 'root' ? null : selectedNodeKeys[0]);
                                    }
                                },
                            },
                        },
                        {
                            toolbar: 'bottom',
                            location: 'after',
                            widget: 'dxButton',
                            options: {
                                text: '取消',
                                onClick: () => {
                                    $popup.dxPopup('instance').hide();
                                },
                            },
                        },
                    ],
                    contentTemplate: () => {
                        return $treeView;
                    },
                    onHidden: () => {
                        $popup.remove();
                    },
                });
            });
        }

        allowCloneToUser() {
            return (
                (this.options.allowCloneToUser &&
                    this.options.onGetUserTemplateDirectories &&
                    this.options.onCloneToUserTemplate) ??
                false
            );
        }

        allowCloneToDepartment() {
            return (
                (this.options.allowCloneToDepartment &&
                    this.options.onGetDepartmentTemplateDirectories &&
                    this.options.onCloneToDepartmentTemplate) ??
                false
            );
        }

        allowCloneToPublic() {
            return (
                (this.options.allowCloneToPublic &&
                    this.options.onGetPublicTemplateDirectories &&
                    this.options.onCloneToPublicTemplate) ??
                false
            );
        }

        preprocessTemplate(template) {
            if (template.isDirectory) {
                template.icon = 'folder';
            } else {
                template.icon = 'file';
            }
            return template;
        }

        removeNodeAndChildren(nodeId) {
            const store = this.treeViewInstance.getDataSource().store();
            const data = store.createQuery().toArray();

            function findAndRemoveChildren(id) {
                const children = data.filter((item) => {
                    return item.parentId === id;
                });
                children.forEach((child) => {
                    findAndRemoveChildren(child.id);
                });
                store.remove(id);
            }

            findAndRemoveChildren(nodeId);

            this.treeViewInstance.getDataSource().reload();
        }

        createDataSource() {
            return new DevExpress.data.ArrayStore({
                key: 'id',
                loadMode: 'raw',
            });
        }

        createTemplateDirectoryForm(templateDirectory) {
            return $('<div class="template-directory-detail-form" />').dxForm({
                colCount: 1,
                formData: templateDirectory || { name: null, bodyParty: null, isDirectory: true },
                items: [
                    {
                        dataField: 'name',
                        validationRules: [
                            {
                                type: 'required',
                                message: '请输入目录名称',
                            },
                        ],
                        label: {
                            text: '目录名称',
                        },
                    },
                    {
                        dataField: 'bodyParty',
                        label: {
                            text: '所属部位',
                        },
                    }
                ],
            });
        }

        createTemplateForm(template) {
            template ??= {};
            template.applicableSex ??= 0;
            template.examResult ??= 0;
            return $('<div class="template-detail-form" />').dxForm({
                colCount: 1,
                formData: template,
                items: [
                    {
                        dataField: 'name',
                        validationRules: [
                            {
                                type: 'required',
                                message: '请输入模板名称',
                            },
                        ],
                        label: {
                            text: '模板名称',
                        },
                    },
                    {
                        dataField: 'applicableSex',
                        editorType: 'dxSelectBox',
                        editorOptions: {
                            displayExpr: 'text',
                            valueExpr: 'value',
                            items: [
                                { text: '不限', value: 0 },
                                { text: '男性', value: 1 },
                                { text: '女性', value: 2 },
                            ],
                        },
                        label: {
                            text: '适用性别',
                        },
                    },
                    {
                        dataField: 'examResult',
                        editorType: 'dxSelectBox',
                        editorOptions: {
                            displayExpr: 'text',
                            valueExpr: 'value',
                            items: [
                                { text: '无', value: 0 },
                                { text: '阴性', value: 1 },
                                { text: '阳性', value: 2 },
                            ],
                        },
                        label: {
                            text: '阴性/阳性',
                        },
                    },
                    {
                        dataField: 'imageSeeing',
                        editorType: 'dxTextArea',
                        editorOptions: {
                            minHeight: 100,
                            autoResizeEnabled: true,
                        },
                        label: {
                            text: '影像所见',
                        },
                    },
                    {
                        dataField: 'imageDiagnosis',
                        editorType: 'dxTextArea',
                        editorOptions: {
                            minHeight: 80,
                            autoResizeEnabled: true,
                        },
                        label: {
                            text: '影像诊断',
                        },
                    },
                    {
                        dataField: 'imageOpinion',
                        editorType: 'dxTextArea',
                        editorOptions: {
                            minHeight: 60,
                            autoResizeEnabled: true,
                        },
                        label: {
                            text: '影像建议',
                        },
                    },
                ],
            });
        }
        async editTemplateForm(template) {
            template = await this.options.onGetTemplate(template);
            template ??= {};
            template.applicableSex ??= 0;
            template.examResult ??= 0;
            return $('<div class="template-detail-form" />').dxForm({
                colCount: 1,
                formData: template,
                items: [
                    {
                        dataField: 'name',
                        validationRules: [
                            {
                                type: 'required',
                                message: '请输入模板名称',
                            },
                        ],
                        label: {
                            text: '模板名称',
                        },
                    },
                    {
                        dataField: 'applicableSex',
                        editorType: 'dxSelectBox',
                        editorOptions: {
                            displayExpr: 'text',
                            valueExpr: 'value',
                            items: [
                                { text: '不限', value: 0 },
                                { text: '男性', value: 1 },
                                { text: '女性', value: 2 },
                            ],
                        },
                        label: {
                            text: '适用性别',
                        },
                    },
                    {
                        dataField: 'examResult',
                        editorType: 'dxSelectBox',
                        editorOptions: {
                            displayExpr: 'text',
                            valueExpr: 'value',
                            items: [
                                { text: '无', value: 0 },
                                { text: '阴性', value: 1 },
                                { text: '阳性', value: 2 },
                            ],
                        },
                        label: {
                            text: '阴性/阳性',
                        },
                    },
                    {
                        dataField: 'imageSeeing',
                        editorType: 'dxTextArea',
                        editorOptions: {
                            minHeight: 100,
                            autoResizeEnabled: true,
                        },
                        label: {
                            text: '影像所见',
                        },
                    },
                    {
                        dataField: 'imageDiagnosis',
                        editorType: 'dxTextArea',
                        editorOptions: {
                            minHeight: 80,
                            autoResizeEnabled: true,
                        },
                        label: {
                            text: '影像诊断',
                        },
                    },
                    {
                        dataField: 'imageOpinion',
                        editorType: 'dxTextArea',
                        editorOptions: {
                            minHeight: 60,
                            autoResizeEnabled: true,
                        },
                        label: {
                            text: '影像建议',
                        },
                    },
                ],
            });
        }

        async newTemplate() {
            if (this.options.onNewTemplate) {
                let template = null;
                if (this.options.onNewTemplateBefore) {
                    template = await this.options.onNewTemplateBefore();
                }
                const templateForm = this.createTemplateForm(template);
                template = await templateForm.formPopup({
                    title: '新建模板',
                    maxWidth: 800,
                    maxHeight: '80vh',
                });
                template = await this.options.onNewTemplate(template, this.selectedTemplate);
                const dataSource = this.treeViewInstance.getDataSource();
                dataSource.store().insert(this.preprocessTemplate(template));
                dataSource.reload();
                this.treeViewInstance.repaint();
                this.selectTemplate(template);
            }
        }

        async newTemplateDirectory() {
            if (this.options.onNewTemplateDirectory && (!this.selectedTemplate || this.selectedTemplate.isDirectory)) {
                const templateDirectoryForm = this.createTemplateDirectoryForm();
                let templateDirectory = await templateDirectoryForm.formPopup({
                    title: '新建目录',
                    maxWidth: 600,
                    maxHeight: 300,
                });
                templateDirectory = await this.options.onNewTemplateDirectory(
                    templateDirectory,
                    this.selectedTemplate
                );
                const dataSource = this.treeViewInstance.getDataSource();
                dataSource.store().insert(this.preprocessTemplate(templateDirectory));
                dataSource.reload();
                this.treeViewInstance.repaint();
                this.selectTemplate(templateDirectory);
            }
        }

        editTemplate(template) {
            if (this.options.onEditTemplate) {
                this.editTemplateForm(template).then(form => {
                    form.formPopup({ title: '编辑模板', maxWidth: 800, maxHeight: '80vh' })
                        .then(template => {
                            this.options.onEditTemplate(template, this.selectedTemplate).then(template => {
                                this.treeViewInstance
                                    .getDataSource()
                                    .store()
                                    .update(template.id, this.preprocessTemplate(template));
                                this.treeViewInstance.repaint();
                                this.selectTemplate(template);
                            });
                        });
                });
            }
        }

        editTemplateDirectory(templateDirectory) {
            if (this.options.onEditTemplateDirectory) {
                this.createTemplateDirectoryForm(templateDirectory)
                    .formPopup({ title: '编辑目录', maxWidth: 600, maxHeight: 300 })
                    .then(templateDirectory => {
                        this.options
                            .onEditTemplateDirectory(templateDirectory, this.selectedTemplate)
                            .then(template => {
                                this.treeViewInstance
                                    .getDataSource()
                                    .store()
                                    .update(template.id, this.preprocessTemplate(template));
                                this.treeViewInstance.repaint();
                                this.selectTemplate(template);
                            });
                    });
            }
        }

        deleteTemplateOrDirectory(template) {
            if (this.options.onDeleteTemplate) {
                this.options.onDeleteTemplate(template).then(() => {
                    this.removeNodeAndChildren(template.id);
                    this.treeViewInstance.repaint();
                });
            }
        }

        selectTemplate(template) {
            this.selectedTemplate = template;
            this.treeViewInstance.selectItem(template?.id);
            if (!template) {
                this.treeViewInstance.unselectAll();
            }
            if (this.options.onTemplateClick) {
                this.options.onTemplateClick(template);
            }
        }

        setReadOnly(readOnly) {
            this.readOnly = readOnly;
            this.$toolbar.dxToolbar('instance').repaint();
        }

        createContextMenu() {
            const $contextmenu = $('<div class="template-context-menu" />');
            $(document.body).append($contextmenu);
            return $contextmenu.dxContextMenu({
                visible: true,
                width: 150,
                dataSource: [
                    {
                        text: '新建',
                        icon: 'add',
                        visible: this.options.allowNew ?? false,
                        items: [
                            {
                                text: '新建模板',
                                icon: 'file',
                                onClick: () => {
                                    this.newTemplate();
                                },
                            },
                            {
                                text: '新建目录',
                                icon: 'inactivefolder',
                                onClick: () => {
                                    this.newTemplateDirectory();
                                },
                            },
                        ],
                    },
                    {
                        text: '编辑',
                        icon: 'edit',
                        beginGroup: true,
                        visible: this.options.allowEdit ?? false,
                        onClick: () => {
                            if (this.selectedTemplate) {
                                if (this.selectedTemplate.isDirectory) {
                                    this.editTemplateDirectory(this.selectedTemplate);
                                } else {
                                    this.editTemplate(this.selectedTemplate);
                                }
                            }
                        },
                    },
                    {
                        text: '删除',
                        icon: 'remove',
                        visible: this.options.allowDelete ?? false,
                        onClick: () => {
                            if (this.selectedTemplate) {
                                DevExpress.ui.dialog.confirm('是否要删除所选择的模板?', '删除').done(result => {
                                    if (result) {
                                        this.deleteTemplateOrDirectory(this.selectedTemplate);
                                    }
                                });
                            }
                        },
                    },
                    {
                        text: '克隆到',
                        icon: 'copy',
                        beginGroup: true,
                        visible: this.options.allowClone ?? false,
                        items: [
                            {
                                text: '克隆到个人模板',
                                icon: 'copy',
                                visible: this.allowCloneToUser(),
                                onClick: () => {
                                    this.options.onGetUserTemplateDirectories().then(directories => {
                                        this.selectTemplateDirectory(directories).then(templateDirectoryId => {
                                            this.options.onCloneToUserTemplate(
                                                this.selectedTemplate,
                                                templateDirectoryId
                                            );
                                        });
                                    });
                                },
                            },
                            {
                                text: '克隆到科室模板',
                                icon: 'copy',
                                visible: this.allowCloneToDepartment(),
                                onClick: () => {
                                    this.options.onGetDepartmentTemplateDirectories().then(directories => {
                                        this.selectTemplateDirectory(directories).then(templateDirectoryId => {
                                            this.options.onCloneToDepartmentTemplate(
                                                this.selectedTemplate,
                                                templateDirectoryId
                                            );
                                        });
                                    });
                                },
                            },
                            {
                                text: '克隆到公共模板',
                                icon: 'copy',
                                visible: this.allowCloneToPublic(),
                                onClick: () => {
                                    this.options.onGetPublicTemplateDirectories().then(directories => {
                                        this.selectTemplateDirectory(directories).then(templateDirectoryId => {
                                            this.options.onCloneToPublicTemplate(
                                                this.selectedTemplate,
                                                templateDirectoryId
                                            );
                                        });
                                    });
                                },
                            },
                        ],
                    },
                    {
                        text: '刷新',
                        icon: 'refresh',
                        beginGroup: true,
                        onClick: () => {
                            this.refresh();
                        },
                    },
                ],
                onHidden: e => {
                    e.component.dispose();
                    $contextmenu.remove();
                },
            });
        }

        createToolbar() {
            return $('<div class="template-toolbar" />').dxToolbar({
                items: [
                    {
                        location: 'before',
                        widget: 'dxDropDownButton',
                        visible: this.options.allowNew ?? false,
                        options: {
                            text: '新建',
                            icon: 'plus',
                            dropDownOptions: {
                                width: 150,
                            },
                            items: [
                                {
                                    text: '新建模板',
                                    icon: 'file',
                                    onClick: () => {
                                        this.newTemplate();
                                    },
                                },
                                {
                                    text: '新建目录',
                                    icon: 'inactivefolder',
                                    onClick: () => {
                                        this.newTemplateDirectory();
                                    },
                                },
                            ],
                        },
                    },
                    {
                        location: 'before',
                        widget: 'dxButton',
                        visible: this.options.allowFilter ?? false,
                        options: {
                            text: '启用过滤',
                            icon: 'filter',
                            onClick: e => {
                                const text = e.component.option('text');
                                e.component.option('text', text === '启用过滤' ? '禁用过滤' : '启用过滤');
                                this.enableFilter = !this.enableFilter;
                                this.refresh();
                            },
                        },
                    },
                    {
                        location: 'before',
                        widget: 'dxButton',
                        visible: this.options.allowCollapse ?? false,
                        options: {
                            text: '全部折叠',
                            icon: 'collapse',
                            onClick: () => {
                                this.treeViewInstance.collapseAll();
                            },
                        },
                    },
                    {
                        location: 'before',
                        widget: 'dxButton',
                        options: {
                            text: '刷新',
                            icon: 'refresh',
                            onClick: () => {
                                this.refresh();
                            },
                        },
                    },
                ],
            });
        }

        createTemplateTree() {
            const dataSource = new DevExpress.data.DataSource({
                store: new DevExpress.data.ArrayStore({
                    key: 'id',
                    loadMode: 'raw',
                    data: [],
                }),
            });
            const $treeView = $('<div class="template-tree" />').dxTreeView({
                dataSource,
                keyExpr: 'id',
                parentIdExpr: 'parentId',
                displayExpr: 'name',
                expandedExpr: 'isExpanded',
                dataStructure: 'plain',
                selectionMode: 'single',
                activeStateEnabled: false,
                focusStateEnabled: false,
                noDataText: null,
                onItemContextMenu: e => {
                    this.selectTemplate(e.itemData);
                    this.createContextMenu();
                    e.event.preventDefault();
                },
                onItemClick: e => {
                    if (e.itemData.isDirectory) {
                        if (e.node.expanded) {
                            e.component.collapseItem(e.itemData);
                        } else {
                            e.component.expandItem(e.itemData);
                        }
                    }
                    if (this.selectedTemplate?.id !== e.itemData.id) {
                        this.selectTemplate(e.itemData);
                    }
                    if (Date.now() - this.itemClickedLastTime < 500 && e.itemData.id === this.lastClickedTemplateId) {
                        if (this.options.onReplaceTemplate && !this.selectedTemplate.isDirectory) {
                            if (this.options.onGetFullTemplate && !this.readOnly) {
                                this.options.onGetFullTemplate(this.selectedTemplate).then(fullTemplate => {
                                    this.options.onReplaceTemplate(fullTemplate);
                                });
                            }
                        }
                    }
                    this.lastClickedTemplateId = e.itemData.id;
                    this.itemClickedLastTime = Date.now();
                },
            });

            $treeView.click((e) => {
                if ($(e.target).hasClass('dx-scrollable-content')) {
                    this.selectTemplate(null);
                }
            });

            if (this.options.allowEdit && this.options.onTemplateDragged) {
                $treeView.draggableTreeView({
                    onNodeDragged: this.options.onTemplateDragged,
                });
            }

            this.treeViewInstance = $treeView.dxTreeView('instance');
            this.refresh();

            return $treeView;
        }

        refresh() {
            this.options.onLoadTemplates(this.enableFilter).then(data => {
                this.treeViewInstance.beginUpdate();
                const dataSource = new DevExpress.data.DataSource({
                    store: new DevExpress.data.ArrayStore({
                        key: 'id',
                        loadMode: 'raw',
                        data: data.map(x => this.preprocessTemplate(x)),
                    }),
                    sort: [{
                        getter: (item) => item,
                        compare: (a, b) => {
                            if (a.isDirectory && !b.isDirectory) {
                                return -1;
                            } else if (!a.isDirectory && b.isDirectory) {
                                return 1;
                            } else {
                                return a.order - b.order;
                            }
                        }
                    }]
                });
                this.treeViewInstance.option('dataSource', dataSource);
                this.selectTemplate(null);
                this.treeViewInstance.endUpdate();
                this.treeViewInstance.repaint();
            });
        }
    }

    $.fn.diagnosisTemplate = function (options) {
        options = options || {};
        const $container = $(this[0]).addClass('diagnosis-template-container');
        const $templateTree = $('<div class="diagnosis-template" />');
        const $templatePreview = $('<div class="template-preview" />');
        const templatePreview = new TemplatePreview({ container: $templatePreview[0], ...options });
        const handleTemplateClick = template => {
            if (options.onGetFullTemplate) {
                options.onGetFullTemplate(template).then(fullTemplate => {
                    templatePreview.previewTemplate(fullTemplate);
                });
            }
        };
        const templateTree = new TemplateTree({
            container: $templateTree[0],
            onTemplateClick: handleTemplateClick,
            ...options,
        });
        $container.append($templateTree).append($templatePreview).splitter({
            orientation: 'h',
            panel2Size: '30%',
        });
        return {
            refresh: templateTree.refresh.bind(templateTree),
            getSelectedTemplate: () => templateTree.selectedTemplate,
            selectTemplate: templateTree.selectTemplate.bind(templateTree),
            setReadOnly: () => { }
        };
    };
})(jQuery);
